﻿namespace Mueller.CoffeeMonitor
#nowarn "40"

open System
open System.IO
open System.Drawing
open System.Reflection
open System.Windows.Forms

type SettingsForm(settings:SettingsV2) as this =
    inherit Form(Width = 395, Height = 240, Text = "CoffeeScript Monitor Settings")

    let mutable settings = settings

    let rec pathsList =
        let view = 
            new ListView(
                Bounds = Rectangle(Point(5, 25), Size(373, 105)),
                View = View.Details,
                LabelEdit = false,
                AllowColumnReorder = false,
                FullRowSelect = true,
                MultiSelect = false,
                GridLines = false,
                Sorting = SortOrder.Ascending
            )
        view.ContextMenu <-
            new ContextMenu 
                [| new MenuItem("Edit &Source Folder", (fun o e -> getCurrent 0 ||> chooseFolder))
                   new MenuItem("Edit &Output Folder", (fun o e -> getCurrent 1 ||> chooseFolder))
                   new MenuItem("&Delete", (fun o e -> view.SelectedItems.[0].Remove())) |]
        view.MouseDoubleClick |> Observable.add (fun e -> view.ContextMenu.Show(view, e.Location))
        view.Columns.Add("Source Folder", 150, HorizontalAlignment.Left) |> ignore
        view.Columns.Add("Output Folder", -2, HorizontalAlignment.Left) |> ignore
        view.Items.AddRange
            [| for (input, output) in settings.Paths do
                   yield ListViewItem([| input; output |? "" |]) |]

        view

    and getCurrent index =
        if pathsList.SelectedItems.Count = 0 then index, None
        else match pathsList.SelectedItems.[0].SubItems.[index].Text with
             | null | "" -> index, None
             | path -> index, Some path

    and chooseFolder index current =
        use folderBrowser = new FolderBrowserDialog(ShowNewFolderButton = true)
        match current with
        | Some p ->
            folderBrowser.SelectedPath <- p
            folderBrowser.Description  <- sprintf "Edit existing selection:\n%s" p
        | None ->
            folderBrowser.Description <- 
                if index = 0 then "Select a folder to monitor for *.coffee files."
                else "Select an output folder."
        current |> Option.iter (fun p -> folderBrowser.SelectedPath <- p)
        match folderBrowser.ShowDialog() with
        | DialogResult.OK ->
            if pathsList.SelectedItems.Count = 0 || (current = None && index = 0) then
                pathsList.Items.Add(ListViewItem([| folderBrowser.SelectedPath; folderBrowser.SelectedPath |])) |> ignore
            else
                let item = pathsList.SelectedItems.[0]
                item.SubItems.[index].Text <- folderBrowser.SelectedPath
                
        | _ -> ()

    let shouldMinify =
        new CheckBox(
            Checked = settings.Minify,
            Text = "Minify Compiled JavaScript",
            Width = 180,
            Location = Point(10, 135)
        )

    let isBare =
        new CheckBox(
            Checked = not settings.CreateWrapper,
            Text = "Omit function wrapper (Bare)",
            Width = 180,
            Location = Point(200, 135)
        )

    let isIced =
        new CheckBox(
            Checked = settings.Iced,
            Text = "Use Iced CoffeeScript",
            Width = 180,
            Location = Point(10, 155)
        )

    let saveChanges () =
        settings <- { Minify = shouldMinify.Checked;
                      CreateWrapper = not isBare.Checked;
                      Iced = isIced.Checked;
                      Paths = pathsList.Items
                              |> Seq.cast<ListViewItem>
                              |> Seq.map (fun x -> (x.SubItems.[0].Text, asOpt x.SubItems.[1].Text))
                              |> List.ofSeq;
                      SettingsLocation = Some this.DesktopLocation }

    let addButton =
        let btn = new Button(Text = "&Add", Location = Point(303, 1))
        btn.Click |> Observable.add (fun _ -> chooseFolder 0 None)
        btn

    let okButton =
        let btn = new Button(Text = "&OK", Location = Point(220, 185), DialogResult = DialogResult.OK)
        btn.Click |> Observable.add (fun _ -> saveChanges(); this.Close())
        btn

    let cancelButton =
        let btn = new Button(Text = "&Cancel", Location = Point(303, 185), DialogResult = DialogResult.Cancel)
        btn.Click |> Observable.add (fun _ -> this.Close())
        btn

    do
        this.Icon   <- new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("CoffeeMonitor.ico"))
        this.FormBorderStyle <- FormBorderStyle.FixedSingle
        this.AcceptButton <- okButton
        this.CancelButton <- cancelButton
        
        this.Controls.AddRange [|
            new Label(Text = "Paths to monitor: right-click to edit.", Width=250, Height=20, Location = Point(5, 5));
            addButton;
            pathsList;
            shouldMinify;
            isBare;
            isIced;
            new Label(Height = 2, Width = 380, Location = Point(5, 180), BorderStyle = BorderStyle.Fixed3D);
            okButton;
            cancelButton
        |]

        this.Load
        |> Observable.add (fun _ -> settings.SettingsLocation |> Option.iter (fun loc -> this.DesktopLocation <- loc))

    member this.Settings
        with get () = settings
        and  set v  = settings <- v

